"""特征工程模块.

本模块负责信用评分系统的特征处理:

1. 商家特征处理
   - 交易维度(25%): 交易额、频率、稳定性
   - 服务维度(20%): 响应速度、退款处理、争议解决
   - 商品维度(20%): 商品质量、描述准确性、库存管理
   - 活跃维度(15%): 店铺年龄、登录频率、活动参与
   - 合规维度(20%): 资质完备性、违规记录、投诉率

2. 用户特征处理
   - 档案维度(15%): 注册时长、身份认证、账户安全
   - 消费维度(25%): 消费总额、购买频率、品类多样性
   - 履约维度(25%): 支付及时性、订单完成率、退货率
   - 信用维度(20%): 投诉率、违约率、争议处理
   - 社交维度(15%): 评价质量、互动频率、社区贡献
"""

from typing import Dict, List, Optional, Tuple

import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler

from ..utils.logger import logger


class FeatureEngineer:
    """特征工程类,处理商家和用户的特征."""
    
    def __init__(self):
        """初始化特征工程类."""
        self.scaler = StandardScaler()
        
    def process_merchant_features(
        self,
        raw_features: Dict[str, float]
    ) -> Dict[str, float]:
        """处理商家特征数据.
        
        Args:
            raw_features: 原始商家特征数据
            
        Returns:
            Dict[str, float]: 处理后的特征数据
            
        特征维度:
            - transaction_score: 交易维度得分
            - service_score: 服务维度得分
            - product_score: 商品维度得分
            - activity_score: 活跃度得分
            - compliance_score: 合规维度得分
        """
        try:
            features = {}
            
            # 交易维度 (25%)
            features["transaction_score"] = self._calculate_transaction_score(
                amount=raw_features.get("transaction_amount", 0),
                count=raw_features.get("transaction_count", 0)
            )
            
            # 服务维度 (20%)
            features["service_score"] = self._calculate_service_score(
                rating=raw_features.get("service_rating", 0)
            )
            
            # 商品维度 (20%)
            features["product_score"] = self._calculate_product_score(
                quality=raw_features.get("product_quality", 0)
            )
            
            # 活跃维度 (15%)
            features["activity_score"] = self._calculate_activity_score(
                activity=raw_features.get("platform_activity", 0)
            )
            
            # 合规维度 (20%)
            features["compliance_score"] = self._calculate_compliance_score(
                compliance=raw_features.get("compliance_score", 0)
            )
            
            return features
            
        except Exception as e:
            logger.error(f"处理商家特征时发生错误: {e}")
            raise
    
    def process_user_features(
        self,
        raw_features: Dict[str, float]
    ) -> Dict[str, float]:
        """处理用户特征数据.
        
        Args:
            raw_features: 原始用户特征数据
            
        Returns:
            Dict[str, float]: 处理后的特征数据
            
        特征维度:
            - consumption_score: 消费维度得分
            - payment_score: 支付维度得分
            - return_score: 退货维度得分
            - complaint_score: 投诉维度得分
            - social_score: 社交维度得分
        """
        try:
            features = {}
            
            # 消费维度 (25%)
            features["consumption_score"] = self._calculate_consumption_score(
                amount=raw_features.get("consumption_amount", 0),
                frequency=raw_features.get("transaction_frequency", 0)
            )
            
            # 支付维度 (25%)
            features["payment_score"] = self._calculate_payment_score(
                reliability=raw_features.get("payment_reliability", 0)
            )
            
            # 退货维度 (20%)
            features["return_score"] = self._calculate_return_score(
                return_rate=raw_features.get("return_rate", 0)
            )
            
            # 投诉维度 (15%)
            features["complaint_score"] = self._calculate_complaint_score(
                complaint_rate=raw_features.get("complaint_rate", 0)
            )
            
            # 社交维度 (15%)
            features["social_score"] = self._calculate_social_score(
                social_score=raw_features.get("social_score", 0)
            )
            
            return features
            
        except Exception as e:
            logger.error(f"处理用户特征时发生错误: {e}")
            raise
    
    def _calculate_transaction_score(
        self,
        amount: float,
        count: int
    ) -> float:
        """计算交易维度得分.
        
        Args:
            amount: 交易金额
            count: 交易次数
            
        Returns:
            float: 交易维度得分(0-100)
        """
        # 对金额和次数进行对数转换,处理大值
        norm_amount = np.log1p(amount)
        norm_count = np.log1p(count)
        
        # 组合得分: 金额权重0.6,次数权重0.4
        return min(100, (norm_amount * 0.6 + norm_count * 0.4))
    
    def _calculate_service_score(self, rating: float) -> float:
        """计算服务维度得分.
        
        Args:
            rating: 服务评分(0-5)
            
        Returns:
            float: 服务维度得分(0-100)
        """
        return min(100, rating * 20)  # 5分制转换为100分制
    
    def _calculate_product_score(self, quality: float) -> float:
        """计算商品维度得分.
        
        Args:
            quality: 商品质量评分(0-5)
            
        Returns:
            float: 商品维度得分(0-100)
        """
        return min(100, quality * 20)  # 5分制转换为100分制
    
    def _calculate_activity_score(self, activity: float) -> float:
        """计算活跃度维度得分.
        
        Args:
            activity: 活跃度指标(0-1)
            
        Returns:
            float: 活跃度维度得分(0-100)
        """
        return min(100, activity * 100)  # 转换为100分制
    
    def _calculate_compliance_score(self, compliance: float) -> float:
        """计算合规维度得分.
        
        Args:
            compliance: 合规指标(0-1)
            
        Returns:
            float: 合规维度得分(0-100)
        """
        return min(100, compliance * 100)  # 转换为100分制
    
    def _calculate_consumption_score(
        self,
        amount: float,
        frequency: int
    ) -> float:
        """计算消费维度得分.
        
        Args:
            amount: 消费金额
            frequency: 消费频率
            
        Returns:
            float: 消费维度得分(0-100)
        """
        norm_amount = np.log1p(amount)
        norm_frequency = np.log1p(frequency)
        return min(100, (norm_amount * 0.7 + norm_frequency * 0.3))
    
    def _calculate_payment_score(self, reliability: float) -> float:
        """计算支付维度得分.
        
        Args:
            reliability: 支付可靠性指标(0-1)
            
        Returns:
            float: 支付维度得分(0-100)
        """
        return min(100, reliability * 100)  # 转换为100分制
    
    def _calculate_return_score(self, return_rate: float) -> float:
        """计算退货维度得分.
        
        Args:
            return_rate: 退货率(0-1)
            
        Returns:
            float: 退货维度得分(0-100)
        """
        return min(100, (1 - return_rate) * 100)  # 退货率越低分数越高
    
    def _calculate_complaint_score(self, complaint_rate: float) -> float:
        """计算投诉维度得分.
        
        Args:
            complaint_rate: 投诉率(0-1)
            
        Returns:
            float: 投诉维度得分(0-100)
        """
        return min(100, (1 - complaint_rate) * 100)  # 投诉率越低分数越高
    
    def _calculate_social_score(self, social_score: float) -> float:
        """计算社交维度得分.
        
        Args:
            social_score: 社交评分(0-1)
            
        Returns:
            float: 社交维度得分(0-100)
        """
        return min(100, social_score * 100)  # 转换为100分制
    
    def normalize_features(
        self,
        features: Dict[str, float]
    ) -> Dict[str, float]:
        """标准化特征值到0-1范围.
        
        Args:
            features: 原始特征值
            
        Returns:
            Dict[str, float]: 标准化后的特征值
        """
        try:
            # 转换为数组进行标准化
            feature_array = np.array(list(features.values())).reshape(1, -1)
            
            # 拟合并转换
            normalized = self.scaler.fit_transform(feature_array)
            
            # 转换回字典格式
            return dict(zip(features.keys(), normalized[0]))
            
        except Exception as e:
            logger.error(f"特征标准化时发生错误: {e}")
            raise
    
    @staticmethod
    def calculate_weighted_score(
        features: Dict[str, float],
        weights: Dict[str, float]
    ) -> Tuple[float, Dict[str, float]]:
        """计算加权得分.
        
        Args:
            features: 特征值
            weights: 权重值
            
        Returns:
            Tuple[float, Dict[str, float]]: 总分和各维度得分
        """
        try:
            dimension_scores = {}
            total_score = 0.0
            
            for feature, value in features.items():
                weight = weights.get(feature, 0)
                dimension_scores[feature] = value
                total_score += value * weight
            
            return total_score, dimension_scores
            
        except Exception as e:
            logger.error(f"计算加权得分时发生错误: {e}")
            raise